package com.tmt.datatable.editor.instance.impl;

import com.tmt.datatable.editor.instance.INewInstance;
import com.tmt.datatable.editor.instance.IObjectInstanceProxy;
import com.tmt.helper.ReflectHelper;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by ThreeManTeam on 2017/6/5.
 */
public class DefaultInstanceFactory implements IObjectInstanceProxy {

    private List<INewInstance> instancers;

    public DefaultInstanceFactory(){
        instancers = new ArrayList<>();
    }

    public void addInstancer(INewInstance iNewInstance){
        instancers.add(iNewInstance);
    }

    @Override
    public boolean support(Class clazz) {
        return instancers.stream().anyMatch(x->x.support(clazz));
    }

    public <T> Object newInstance(T object, String fieldName, Map<String, Object> newRootPropObjectMap){
        Object result = null;

        String curProp = fieldName.split("\\[")[0];
        Class actualClazz = ReflectHelper.getActualClassByFieldName(object.getClass(), curProp);
        Class clazz = ReflectHelper.getFieldClassByFieldName(object.getClass(), curProp);
        if (clazz == null)
            return null;

        List<Class> classList = new ArrayList<>();
        classList.add(actualClazz);
        if (clazz != actualClazz)
            classList.add(clazz);

        try {
            for (Class aClassList : classList) {
                for (INewInstance instancer : instancers) {
                    if (instancer.support(aClassList))
                        result = instancer.newInstance(object, fieldName, newRootPropObjectMap);
                    if (result != null) break;
                }
                if (result != null) break;
            }
        }catch (Exception ex){}

        if (result == null) {
            try {
                result = ReflectHelper.getFieldValue(object, curProp);
                if (result == null) {
                    result = clazz.newInstance();
                    if (newRootPropObjectMap != null && newRootPropObjectMap.isEmpty())
                        newRootPropObjectMap.put(curProp, object);
                }
            }catch (Exception ex){}
        }

        return result;
    }

}
